home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
tex
/
td187src.lzh
/
OBJECTUT.I
< prev
next >
Wrap
Text File
|
1991-12-14
|
48KB
|
1,506 lines
IMPLEMENTATION MODULE ObjectUtilities;
(*
Faßt ein paar häufiger benötigte Standardaufgaben im Zusammenhang
mit Zeichenobjekten zusammen, Redraw etc.
*)
(* Import list *)
IMPORT mtAppl;
IMPORT Diverses;
IMPORT MagicAES;
IMPORT MagicVDI;
IMPORT Bezier;
IMPORT Circles;
IMPORT Epic ;
IMPORT Fill;
IMPORT GetFile;
IMPORT Lines;
IMPORT MathLib0;
IMPORT MagicStrings;
IMPORT MagicSys;
IMPORT TextBox;
IMPORT WinUtils;
FROM CommonData IMPORT WindowHandle, WindowTitle,
ClipXY, OffsetXY, WorkArea,
FileName, LineWidth, TextPosition,
XPosx, XPosy, YPosx, YPosy,
DXPosx, DXPosy, DYPosx, DYPosy,
WholeArea, ZeroX, ZeroY,
InternalResolution,
SnapX, SnapY,
FatherXOffset, FatherYOffset;
FROM HelpModule IMPORT LastHelpMessage, WinSize;
FROM Types IMPORT TextPosTyp, DrawObjectTyp, CodeAryTyp,
ObjectSet, CharPtrTyp, ObjectPtrTyp,
Block, ObjectRecTyp ;
FROM SYSTEM IMPORT ADR;
FROM Variablen IMPORT FirstObject, LastObject,
NewObject, DeleteObject,
PicToPix, PixToPic,
ValueToStr, CoordToStr,
PicDistance, PixDistance,
Visible, MergeToSubpic,
RefObject;
(**
IMPORT RTD;
**)
CONST ChangeBox = 2;
(* global structures and variables **)
TYPE CXYresproc = PROCEDURE (VAR INTEGER, VAR INTEGER, VAR INTEGER,
VAR INTEGER, VAR INTEGER,
VAR INTEGER, VAR INTEGER);
LXYresproc = PROCEDURE (VAR INTEGER, VAR INTEGER, VAR INTEGER,
VAR INTEGER,
VAR INTEGER, VAR INTEGER, VAR INTEGER);
Mirrorproc = PROCEDURE (VAR INTEGER, VAR INTEGER, VAR INTEGER,
VAR INTEGER, VAR INTEGER, VAR INTEGER,
VAR INTEGER, VAR INTEGER);
ShowObjProc = PROCEDURE ( ObjectPtrTyp );
VAR ShowProcedures : ARRAY DrawObjectTyp OF ShowObjProc;
ShowAllMode : BOOLEAN;
Internal : BOOLEAN;
(**
ReallyAll : BOOLEAN;
DrawSet : ObjectSet;
**)
(** zu Debug-Zwecken
ShowText : ARRAY DrawObjectTyp OF ARRAY [0..15] OF CHAR;
**)
PROCEDURE BeginStandardVDI;
VAR dum : INTEGER;
BEGIN
(* Setze jetzt die Standardwerte, damit die nicht *)
(* andauernd neu gesetzt werden müssen... *)
dum := MagicVDI.SetLinetype ( mtAppl.VDIHandle , MagicVDI.Line ) ;
dum := MagicVDI.SetLinecolor ( mtAppl.VDIHandle , MagicAES.BLACK ) ;
dum := MagicVDI.SetMarkertype(mtAppl.VDIHandle, MagicVDI.Point);
dum := MagicVDI.SetMarkercolor(mtAppl.VDIHandle, MagicAES.BLACK);
MagicVDI.SetLineEndstyles ( mtAppl.VDIHandle ,
MagicVDI.Cornerd , MagicVDI.Cornerd ) ;
dum := MagicVDI.SetFillinterior (mtAppl.VDIHandle , MagicVDI.Full ) ;
dum := MagicVDI.SetFillcolor ( mtAppl.VDIHandle , MagicAES.BLACK ) ;
END BeginStandardVDI;
PROCEDURE EndStandardVDI;
VAR dum : INTEGER;
BEGIN
BeginStandardVDI;
END EndStandardVDI;
(*
Jetzt die diversen Prozeduren zum Bestimmen der Schnittpunkte
der Linien mit einem umgebenden Kreis.
Alle gehen davon aus, daß der Mittelpunkt die Koordinaten 0,0 hat.
*)
PROCEDURE CHorizRes(VAR y, RX, RY, X1, Y1, X2, Y2 : INTEGER);
BEGIN
Y1 := y; Y2 := y;
X2 := Diverses.round(
MathLib0.sqrt(MathLib0.real(RX*RX) -
MathLib0.real(RX*RX)/MathLib0.real(RY*RY)*MathLib0.real(y*y)));
X1 := - X2;
END CHorizRes;
PROCEDURE CVertiRes(VAR x, RX, RY, X1, Y1, X2, Y2 : INTEGER);
BEGIN
X1 := x; X2 := x;
Y2 := Diverses.round(MathLib0.sqrt(MathLib0.real(RY*RY) -
MathLib0.real(RY*RY)/MathLib0.real(RX*RX)*MathLib0.real(x*x)));
Y1 := - Y2;
END CVertiRes;
PROCEDURE CRightRes(VAR A, RX, RY, X1, Y1, X2, Y2 : INTEGER);
VAR rx, ry, num, x1, x2, y1, y2, a : LONGREAL;
check : INTEGER;
BEGIN
(*
Also wir benötigen die Schnittpunkte der Geraden:
y = x - a
mit der Ellipsen:
y^2 / RY^2 + x^2/RX^2 = 1
Also:
=> (x - a)^2 / RY^2 + x^2/RX^2 = 1
=> RX^2 x^2 - 2 RX^2 a x + RX^2 a^2 + RY^2 x^2 = RX^2 RY^2
=> (RX^2 + RY^2) x^2 - 2 RX^2 a x + RX^2 a^2 - RX^2 RY^2 = 0
=> x^2 - (2 RX^2 a)/(RX^2 + RY^2) x +
(RX^2 a^2 - RX^2 RY^2)/(RX^2 + RY^2) = 0
=> 2 reelle Lösungen für x:
_______________________________________
RX^2 a / RX^4 a^2 RX^2 a^2 - RX^2 RY^2
x_1_2 = ----------- +- _ / --------------- - --------------------
RX^2 + RY^2 \/ (RX^2 + RY^2)^2 (RX^2 + RY^2)
=> läßt sich "vereinfachen" zu:
__________________
RX^2 RX RY /
x_1_2 = ----------- a +- ----------- _ / RX^2 + RY^2 - a^2
RX^2 + RY^2 RX^2 + RY^2 \/
Im Falle eines Kreises (RX=RY=R) vereinfacht sich dieser Ausdruck zu:
___________
1 ( / )
x_1_2 = --- ( a +- _ / R^2 - a^2 )
2 ( \/ )
*)
rx := MathLib0.real(RX);
ry := MathLib0.real(RY);
a := MathLib0.real(A);
IF (rx*rx + ry*ry - a*a) >=0.0 THEN
num := (rx * ry) / (rx*rx + ry*ry) * MathLib0.sqrt(rx*rx + ry*ry - a*a);
x1 := (a * rx*rx) / (rx*rx + ry*ry) - num;
y1 := MathLib0.sqrt ( ry*ry - (ry*ry) / (rx*rx) * x1 * x1 );
x2 := (a * rx*rx) / (rx*rx + ry*ry) + num;
X1 := Diverses.round( x1 );
X2 := Diverses.round( x2 );
Y1 := -Diverses.round( y1 );
Y2 := Y1 + (X2 - X1);
IF A = RX THEN
X1 := 0; Y1 := -RY; X2 := RX; Y2 := 0;
END;
(* Jetzt korrigiere eventuelle Ungenauigkeiten,
damit die Linien immer gleichen Abstand haben. *)
check := X1 - Y1;
IF check<>A THEN
X1 := X1 + (A-check);
X2 := X2 + (A-check);
END;
ELSE
X1 := 0; Y1 := 0;
X2 := 0; Y2 := 0;
END;
(**
RTD.ShowVar('x', A);
RTD.ShowVar('RX', RX);
RTD.ShowVar('RY', RY);
RTD.ShowVar('X1', X1);
RTD.ShowVar('Y1', Y1);
RTD.ShowVar('X2', X2);
RTD.ShowVar('Y2', Y2);
**)
END CRightRes;
PROCEDURE CLeftRes(VAR x, RX, RY, X1, Y1, X2, Y2 : INTEGER);
VAR i, j, k, l : INTEGER;
BEGIN
CRightRes(x, RX, RY, i, j, k, l);
X1 := -k;
Y1 := l;
X2 := -i;
Y2 := j;
END CLeftRes;
PROCEDURE CHorizMirror(VAR X1, Y1, X2, Y2, X3, Y3, X4, Y4 : INTEGER);
BEGIN
X3 := X1; X4 := X2;
Y3 := -Y1; Y4 := -Y2;
END CHorizMirror;
PROCEDURE CVertiMirror(VAR X1, Y1, X2, Y2, X3, Y3, X4, Y4 : INTEGER);
BEGIN
X3 := -X1; X4 := -X2;
Y3 := Y1; Y4 := Y2;
END CVertiMirror;
PROCEDURE CLeftRightMirror(VAR X1, Y1, X2, Y2, X3, Y3, X4, Y4 : INTEGER);
BEGIN
X4 := -X1; Y4 := -Y1;
X3 := -X2; Y3 := -Y2;
END CLeftRightMirror;
(*
Jetzt die diversen Prozeduren zum Bestimmen der Schnittpunkte
der Linien mit einem umgebenden Rechteck.
Alle gehen davon aus, daß der Mittelpunkt die Koordinaten 0,0 hat.
*)
PROCEDURE LHorizRes(VAR x, W, H, X1, Y1, X2, Y2 : INTEGER);
BEGIN
X1 := 0; X2 := W;
Y1 := x; Y2 := x;
END LHorizRes;
PROCEDURE LVertiRes(VAR x, W, H, X1, Y1, X2, Y2 : INTEGER);
BEGIN
X1 := x; X2 := x;
Y1 := 0; Y2 := H;
END LVertiRes;
PROCEDURE LLeftRes(VAR x, W, H, X1, Y1, X2, Y2 : INTEGER);
BEGIN
(* Jetzt wird's schon komplizierter *)
X1 := 0;
Y1 := x;
X2 := x;
Y2 := 0;
IF Y1>H THEN
X1 := x-H;
Y1 := H;
END;
IF (X2>W) THEN
X2 := W;
Y2 := x-W;
END;
END LLeftRes;
PROCEDURE LRightRes(VAR x, W, H, X1, Y1, X2, Y2 : INTEGER);
BEGIN
(* Jetzt wird's schon komplizierter *)
X1 := x;
Y1 := 0;
X2 := H + x;
Y2 := H;
IF X1<0 THEN
X1 := 0;
Y1 := -x;
END;
IF (X2>W) THEN
X2